package com.timebank.common.chaincode.contract;

import com.alibaba.fastjson2.JSON;
import com.timebank.common.chaincode.entity.User;
import org.hyperledger.fabric.contract.Context;
import org.hyperledger.fabric.contract.ContractInterface;
import org.hyperledger.fabric.contract.annotation.Contract;
import org.hyperledger.fabric.contract.annotation.Default;
import org.hyperledger.fabric.contract.annotation.Transaction;
import org.hyperledger.fabric.shim.ChaincodeException;
import org.hyperledger.fabric.shim.ChaincodeStub;
import org.hyperledger.fabric.shim.ledger.KeyValue;
import org.hyperledger.fabric.shim.ledger.QueryResultsIterator;

import java.util.ArrayList;
import java.util.List;

/**
 * 智能合约
 * @author shiliuyinzhen
 */
@Default
@Contract(name = "userContract")
public class UserContract implements ContractInterface {

    public UserContract(){}

    /**
     * 初始化3条记录
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public void init(final Context ctx) {
        addUser(ctx, "107", "shiliuyinzhen",10000D);
        addUser(ctx, "108", "admin",10000D);
    }

    /**
     * 新增用户
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public User addUser(final Context ctx, final String userId, final String name, final double timeCoin) {
        ChaincodeStub stub = ctx.getStub();
        User user = new User(userId, name, timeCoin);
        String userJson = JSON.toJSONString(user);
        stub.putStringState(userId, userJson);
        return user;
    }

    /**
     * 查询某个用户
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public User getUser(final Context ctx, final String userId) {
        ChaincodeStub stub = ctx.getStub();
        String userJSON = stub.getStringState(userId);
        if (userJSON == null || userJSON.isEmpty()) {
            String errorMessage = String.format("User %s does not exist", userId);
            throw new ChaincodeException(errorMessage);
        }
        User user = JSON.parseObject(userJSON, User.class);
        return user;
    }

    /**
     * 查询所有用户
     */
    @Transaction(intent = Transaction.TYPE.EVALUATE)
    public String queryAll(final Context ctx) {
        ChaincodeStub stub = ctx.getStub();
        List<User> userList = new ArrayList<>();
        QueryResultsIterator<KeyValue> results = stub.getStateByRange("", "");
        for (KeyValue result: results) {
            User user = JSON.parseObject(result.getStringValue(), User.class);
            System.out.println(user);
            userList.add(user);
        }
        return JSON.toJSONString(userList);
    }

    /**
     * 转账
     * @param sourceId 源用户id
     * @param targetId 目标用户id
     * @param timeCoin 金额
     */
    @Transaction(intent = Transaction.TYPE.SUBMIT)
    public void transfer(final Context ctx, final String sourceId, final String targetId, final double timeCoin) {
        ChaincodeStub stub = ctx.getStub();
        User sourceUser = getUser(ctx, sourceId);
        User targetUser = getUser(ctx, targetId);
        if (sourceUser.getTimeCoin() < timeCoin) {
            String errorMessage = String.format("The balance of user %s is insufficient", sourceId);
            throw new ChaincodeException(errorMessage);
        }
        User newSourceUser = new User(sourceUser.getUserId(), sourceUser.getUserName(), sourceUser.getTimeCoin() - timeCoin);
        User newTargetUser = new User(targetUser.getUserId(), targetUser.getUserName(), targetUser.getTimeCoin() + timeCoin);
        stub.putStringState(sourceId, JSON.toJSONString(newSourceUser));
        stub.putStringState(targetId, JSON.toJSONString(newTargetUser));
    }
}
